AvgPoolFusion ================= 对 **NHWC** 输入做 2D 平均池化,再按 ``[minf, maxf]`` 做范围裁剪(Clip)。 池化窗口落到填充区时,只对落在有效输入内的元素求平均(分母为有效点数,而非固定 :math:`k_h \times k_w`)。 对输出位置 :math:`(b, y, x, c)`,令窗口起点 :math:`y_0 = y \cdot s_h - pad_u`,:math:`x_0 = x \cdot s_w - pad_l`, 有效窗口为与输入相交的部分,有效点数为 :math:`R`: .. math:: \begin{aligned} P &= \frac{1}{R} \sum_{(m,n) \in \mathrm{valid}} I[b,\, y_0 + m,\, x_0 + n,\, c] \\ O &= \max(\mathrm{minf},\, \min(P,\, \mathrm{maxf})) \end{aligned} 若 :math:`R = 0`,则 :math:`P = 0` 后再裁剪。 输入: - **input** - 输入数据地址,格式 NHWC - **params** - ``long long`` 参数数组,长度至少 14,布局见下 - **core_mask** - 核掩码(仅共享存储版本使用) **params 布局:** - ``[0]`` ``in_w`` - 输入宽 - ``[1]`` ``in_h`` - 输入高 - ``[2]`` ``win_w`` - 池化核宽 - ``[3]`` ``win_h`` - 池化核高 - ``[4]`` ``output_w`` - 输出宽 - ``[5]`` ``output_h`` - 输出高 - ``[6]`` ``batch`` - batch 大小 - ``[7]`` ``channel`` - 通道数 - ``[8]`` ``stride_w`` - 水平步长 - ``[9]`` ``stride_h`` - 垂直步长 - ``[10]`` ``pad_l`` - 左侧填充 - ``[11]`` ``pad_u`` - 上侧填充 - ``[12]`` ``minf`` - 裁剪下限地址(指针,不是数值本身) - ``[13]`` ``maxf`` - 裁剪上限地址(指针,不是数值本身) 输出: - **output** - 输出数据地址,格式 NHWC 支持平台: ``FT78NE`` ``MT7004`` .. note:: - FT78NE 支持 int8、fp32 - MT7004 支持 fp16、fp32 - ``params[12]`` / ``params[13]`` 须传入 ``minf`` / ``maxf`` 的地址;``hp_`` 版本指向 ``float16``,``fp_`` / ``i8_`` 版本指向 ``float`` / ``int8_t`` 对应存储 **共享存储版本:** .. c:function:: void i8_avg_pooling_s(int8_t *input, int8_t *output, long long *params, int core_mask) .. c:function:: void hp_avg_pooling_s(float16 *input, float16 *output, long long *params, int core_mask) .. c:function:: void fp_avg_pooling_s(float *input, float *output, long long *params, int core_mask) **C调用示例:** .. code-block:: c :linenos: :emphasize-lines: 28 // MT7004 示例(共享存储多核,DDR 地址) void TestAvgPoolFusionSMCFp32(int core_mask) { int core_id = get_core_id(); int logic_core_id = GetLogicCoreId(core_mask, core_id); int core_num = GetCoreNum(core_mask); float *input = (float *)0x81000000; float *output = (float *)0x90000000; float minf = 0.0f; float maxf = 50.0f; long long params[16]; if (logic_core_id == 0) { params[0] = 16; // in_w params[1] = 16; // in_h params[2] = 2; // win_w params[3] = 2; // win_h params[4] = 8; // output_w params[5] = 8; // output_h params[6] = 1; // batch params[7] = 16; // channel params[8] = 2; // stride_w params[9] = 2; // stride_h params[10] = 0; // pad_l params[11] = 0; // pad_u params[12] = (long long)&minf; params[13] = (long long)&maxf; } sys_bar(0, core_num); fp_avg_pooling_s(input, output, params, core_mask); } void main() { int core_mask = 0b1111; TestAvgPoolFusionSMCFp32(core_mask); } **私有存储版本:** .. c:function:: void i8_avg_pooling_p(int8_t *input, int8_t *output, long long *params) .. c:function:: void hp_avg_pooling_p(float16 *input, float16 *output, long long *params) .. c:function:: void fp_avg_pooling_p(float *input, float *output, long long *params) **C调用示例:** .. code-block:: c :linenos: :emphasize-lines: 22 // MT7004 示例(私有存储单核,AM 地址) void TestAvgPoolFusionAMFp32(void) { float *input = (float *)0x10000000; float *output = (float *)0x10020000; float minf = 0.0f; float maxf = 50.0f; long long params[16]; params[0] = 16; // in_w params[1] = 16; // in_h params[2] = 2; // win_w params[3] = 2; // win_h params[4] = 8; // output_w params[5] = 8; // output_h params[6] = 1; // batch params[7] = 16; // channel params[8] = 2; // stride_w params[9] = 2; // stride_h params[10] = 0; // pad_l params[11] = 0; // pad_u params[12] = (long long)&minf; params[13] = (long long)&maxf; fp_avg_pooling_p(input, output, params); } void main() { TestAvgPoolFusionAMFp32(); }